﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text;
using UAC.Common;
using UAC.Data;
using UAC.Operation;

namespace UAC
{
    public class Utils
    {
        private static string dbPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "System.db");
        private static readonly object locker = new object();
        static Utils()
        {
            DataHelper.SetSQLiteConnection(dbPath);
        }

        private static List<DocumentDef> documentDefs;
        public static List<DocumentDef> ListDocumentDef()
        {
            lock (locker)
            {
                documentDefs = new List<DocumentDef>();
                //TODO:Load DocumentDef List
                string sql = "select id,documentdefid,name,description,remarks,state from sy_documentdef";
                DataTable result = DataHelper.GetDataTableBySql(sql);
                if (result != null)
                {
                    foreach (DataRow dr in result.Rows)
                        documentDefs.Add(new DocumentDef(dr));
                }
            }
            return documentDefs;
        }

        public static DocumentDef CreateDocumentDef(int documentdefid, string name, string description, string remarks)
        {
            string token = RandomString.GetRandomString(10);
            bool isExist = DataHelper.HasRow(string.Format("select * from sy_documentdef where documentdefid={0}", documentdefid));
            if (isExist)
                throw new Exception("已经存在DocumentDef相同的项");
            string sqlStr = string.Format("insert into sy_documentdef(documentdefid,name,description,remarks,state,time,token) values({0},'{1}','{2}','{3}',1,'{4:yyyy-MM-dd HH:mm:ss}','{5}')", documentdefid, DataHelper.EncodeS(name), DataHelper.EncodeS(description), DataHelper.EncodeS(remarks), DateTime.Now, token);
            DataHelper.ExecuteNonQuery(sqlStr);
            object id = DataHelper.ExecuteScalar(string.Format("select id from sy_documentdef where token='{0}'", token));
            return new DocumentDef() { ID = Convert.ToInt32(id), Name = name, Description = description, DocumentDefID = documentdefid, Remarks = remarks, State = 1 };
        }

        /// <summary>
        /// 列举DocumentFieldDef
        /// </summary>
        /// <param name="documentDefID"></param>
        /// <returns></returns>
        public static List<DocumentFieldDef> ListDocumentFieldDef(int documentDefID)
        {
            List<DocumentFieldDef> documentFieldDefs = new List<DocumentFieldDef>();
            string sql = string.Format("select id,documentdefid,name,description from sy_documentfielddef where documentdefid={0}", documentDefID);
            DataTable result = DataHelper.GetDataTableBySql(sql);
            if (result != null)
            {
                foreach (DataRow dr in result.Rows)
                    documentFieldDefs.Add(new DocumentFieldDef(dr));
            }
            return documentFieldDefs;
        }

        public static DocumentFieldDef CreateDocumentFieldDef(int documentDefID, string name, string description)
        {
            bool isExist = DataHelper.HasRow(string.Format("select * from sy_documentfielddef where documentdefid={0} and name='{1}'", documentDefID, name));
            if (isExist)
                throw new Exception("已经存在DocumentFieldDef相同的项");
            DocumentFieldDef documentFieldDef = new DocumentFieldDef() { Name = name, DocumentDefID = documentDefID, Description = description };
            string token = RandomString.GetRandomString(10);
            string sql = string.Format("insert into sy_documentfielddef(documentdefid,name,description,token,time) values({0},'{1}','{2}','{3}','{4:yyyy-MM-dd HH:mm:ss}')", documentDefID, DataHelper.EncodeS(name), DataHelper.EncodeS(description), token, DateTime.Now);
            DataHelper.ExecuteNonQuery(sql);
            object id = DataHelper.ExecuteScalar(string.Format("select id from sy_documentfielddef where token='{0}'", token));
            documentFieldDef.ID = Convert.ToInt32(id);
            return documentFieldDef;
        }

        /// <summary>
        /// 列举DocumentDef
        /// </summary>
        /// <param name="documentDefID"></param>
        /// <returns></returns>
        public static List<OperationDef> ListOperationDef(int documentDefID)
        {
            List<OperationDef> operationDefs = new List<OperationDef>();
            string sql = string.Format("select id,documentdefid,operationdefid,name,description,ocid from sy_operationdef where documentdefid={0}", documentDefID);
            DataTable result = DataHelper.GetDataTableBySql(sql);
            if (result != null)
            {
                foreach (DataRow dr in result.Rows)
                    operationDefs.Add(new OperationDef(dr));
            }
            return operationDefs;
        }

        public static OperationDef CreateOperationDef(int documentdefid, int operationdefid, string name, string description, int ocid = -1)
        {
            string token = RandomString.GetRandomString(10);
            bool isExist = DataHelper.HasRow(string.Format("select * from sy_operationdef where operationdefid={0}", operationdefid));
            if (isExist)
                throw new Exception("已经存在OperationDef相同的项");
            string sqlStr = string.Format("insert into sy_operationdef(documentdefid,name,description,operationdefid,ocid,token) values({0},'{1}','{2}',{3},{4},'{5}')", documentdefid, DataHelper.EncodeS(name), DataHelper.EncodeS(description), operationdefid, ocid, token);
            DataHelper.ExecuteNonQuery(sqlStr);
            object id = DataHelper.ExecuteScalar(string.Format("select id from sy_operationdef where token='{0}'", token));
            return new OperationDef() { ID = Convert.ToInt32(id), Name = name, Description = description, DocumentDefID = documentdefid, OperationDefID = operationdefid, OCID = ocid };
        }

        public static void AddOperationControl(ControlCondition condition, int parentId = -1)
        {
            string token = RandomString.GetRandomString(10);
            string sql = string.Format("insert into sy_conditions(documentdefid,description,type1,value1,type2,value2,type3,value3,type4,value4,type5,value5,parentid,token) values({0},'{1}',{2},'{3}',{4},'{5}',{6},'{7}',{8},'{9}',{10},'{11}',{12},'{13}')", condition.DocumentDefID, condition.Description, ConditionValue.GetType(condition.Values1), DataHelper.EncodeS(ConditionValue.GetValue(condition.Values1)), ConditionValue.GetType(condition.Values2), DataHelper.EncodeS(ConditionValue.GetValue(condition.Values2)), ConditionValue.GetType(condition.Values3), DataHelper.EncodeS(ConditionValue.GetValue(condition.Values3)), ConditionValue.GetType(condition.Values4), DataHelper.EncodeS(ConditionValue.GetValue(condition.Values4)), ConditionValue.GetType(condition.Values5), DataHelper.EncodeS(ConditionValue.GetValue(condition.Values5)), parentId, token);
            DataHelper.ExecuteNonQuery(sql);
            object id = DataHelper.ExecuteScalar(string.Format("select id from sy_conditions where token='{0}'", token));
            condition.ID = Convert.ToInt32(id);

            DataHelper.ExecuteNonQuery(string.Format("insert into sy_conditionrelations(documentdefid,parentid,type,token) values({0},{1},{2},'{3}')", condition.DocumentDefID, condition.ID, (int)condition.OperationType, token));
            if ((condition.OperationType == OperationType.Or || condition.OperationType == OperationType.And) && condition.ConditionList != null)
            {
                foreach (ControlCondition child in condition.ConditionList)
                {
                    AddOperationControl(child, condition.ID);
                }
            }
        }

        public static void UpdateOperationControl(ControlCondition condition, int parentId = -1)
        {
            if (condition != null)
            {
                if (condition.ID == -1)
                {
                    AddOperationControl(condition, parentId);
                    return;
                }
                string sql = string.Format("update sy_conditions set description='{1}',type1={2},value1='{3}',type2={4},value2='{5}',type3={6},value3='{7}',type4={8},value4='{9}',type5={10},value5='{11}' where id={0}", condition.ID, condition.Description, ConditionValue.GetType(condition.Values1), DataHelper.EncodeS(ConditionValue.GetValue(condition.Values1)), ConditionValue.GetType(condition.Values2), DataHelper.EncodeS(ConditionValue.GetValue(condition.Values2)), ConditionValue.GetType(condition.Values3), DataHelper.EncodeS(ConditionValue.GetValue(condition.Values3)), ConditionValue.GetType(condition.Values4), DataHelper.EncodeS(ConditionValue.GetValue(condition.Values4)), ConditionValue.GetType(condition.Values5), DataHelper.EncodeS(ConditionValue.GetValue(condition.Values5)));
                DataHelper.ExecuteNonQuery(sql);

                DataHelper.ExecuteNonQuery(string.Format("update sy_conditionrelations set type={2} where parentid={0},documentdefid={1}", condition.ID, condition.DocumentDefID, (int)condition.OperationType));
                if (condition.ConditionList == null)
                    DataHelper.ExecuteNonQuery(string.Format("delete from sy_conditions where parentid={0}", condition.ID));
                else
                {
                    foreach (ControlCondition child in condition.ConditionList)
                    {
                        UpdateOperationControl(child, condition.ID);
                    }
                }

            }
        }

        /// <summary>
        /// 列举ControlCondition
        /// </summary>
        /// <param name="documentDefID"></param>
        /// <returns></returns>
        public static List<ControlCondition> ListOperationControl(int documentDefID)
        {
            List<ControlCondition> conditions = GetChildOperationControls(documentDefID, -1);
            return conditions;
        }

        public static ControlCondition GetControlCondition(int operationdefid)
        {
            string strSql = string.Format("select ocid,documentdefid from sy_operationdef where operationdefid={0}", operationdefid);
            DataTable result = DataHelper.GetDataTableBySql(strSql);
            int documentDefID = Convert.ToInt32(result.Rows[0][1]);
            int conditionId = Convert.ToInt32(result.Rows[0][0]);
            ControlCondition condition = GetOperationControlCondition(documentDefID, conditionId);
            return condition;
        }

        #region Private
        private static OperationType GetControlOperationType(int documentDefID, int id)
        {
            string relationSql = string.Format("select type from sy_conditionrelations where documentdefid={0} and parentid={1}", documentDefID, id);
            object relationType = DataHelper.ExecuteScalar(relationSql);
            return (OperationType)Enum.ToObject(typeof(OperationType), relationType);
        }


        private static ControlCondition GetOperationControlCondition(int documentDefID, int conditionId)
        {
            string sql = string.Format("select id,documentdefid,parentid,description,type1,value1,type2,value2,type3,value3,type4,value4,type5,value5 from sy_conditions where id={0} and documentdefid={1}", conditionId, documentDefID);
            DataTable result = DataHelper.GetDataTableBySql(sql);
            if (result != null)
            {
                foreach (DataRow dr in result.Rows)
                {
                    int id = Convert.ToInt32(dr["id"]);
                    ControlCondition condition = new ControlCondition() { ID = id, DocumentDefID = documentDefID, Description = dr["description"].ToString() };
                    condition.OperationType = GetControlOperationType(documentDefID, id);

                    List<ControlCondition> children = GetChildOperationControls(documentDefID, id);
                    if (children == null || children.Count == 0)
                    {
                        if (dr["type1"] != DBNull.Value)
                            condition.Values1 = new ConditionValue() { ValueType = (UAC.Operation.ValueType)Enum.ToObject(typeof(UAC.Operation.ValueType), Convert.ToInt32(dr["type1"])), Value = dr["value1"] };
                        if (dr["type2"] != DBNull.Value)
                            condition.Values2 = new ConditionValue() { ValueType = (UAC.Operation.ValueType)Enum.ToObject(typeof(UAC.Operation.ValueType), Convert.ToInt32(dr["type2"])), Value = dr["value2"] };
                        if (dr["type3"] != DBNull.Value)
                            condition.Values3 = new ConditionValue() { ValueType = (UAC.Operation.ValueType)Enum.ToObject(typeof(UAC.Operation.ValueType), Convert.ToInt32(dr["type3"])), Value = dr["value3"] };
                        if (dr["type4"] != DBNull.Value)
                            condition.Values4 = new ConditionValue() { ValueType = (UAC.Operation.ValueType)Enum.ToObject(typeof(UAC.Operation.ValueType), Convert.ToInt32(dr["type4"])), Value = dr["value4"] };
                        if (dr["type5"] != DBNull.Value)
                            condition.Values5 = new ConditionValue() { ValueType = (UAC.Operation.ValueType)Enum.ToObject(typeof(UAC.Operation.ValueType), Convert.ToInt32(dr["type5"])), Value = dr["value5"] };
                    }
                    else
                        condition.ConditionList = children;
                    return condition;
                }
            }
            return null;
        }

        private static List<ControlCondition> GetChildOperationControls(int documentDefID, int parentid)
        {
            List<ControlCondition> conditions = new List<ControlCondition>();
            string sql = string.Format("select id,documentdefid,parentid,description,type1,value1,type2,value2,type3,value3,type4,value4,type5,value5 from sy_conditions where documentdefid={0} and parentid={1}", documentDefID, parentid);
            DataTable result = DataHelper.GetDataTableBySql(sql);
            if (result != null)
            {
                foreach (DataRow dr in result.Rows)
                {
                    int id = Convert.ToInt32(dr["id"]);
                    ControlCondition condition = new ControlCondition() { ID = id, DocumentDefID = documentDefID, Description = dr["description"].ToString() };
                    condition.OperationType = GetControlOperationType(documentDefID, id);

                    List<ControlCondition> children = GetChildOperationControls(documentDefID, id);
                    if (children == null || children.Count == 0)
                    {
                        if (dr["type1"] != DBNull.Value)
                            condition.Values1 = new ConditionValue() { ValueType = (UAC.Operation.ValueType)Enum.ToObject(typeof(UAC.Operation.ValueType), Convert.ToInt32(dr["type1"])), Value = dr["value1"] };
                        if (dr["type2"] != DBNull.Value)
                            condition.Values2 = new ConditionValue() { ValueType = (UAC.Operation.ValueType)Enum.ToObject(typeof(UAC.Operation.ValueType), Convert.ToInt32(dr["type2"])), Value = dr["value2"] };
                        if (dr["type3"] != DBNull.Value)
                            condition.Values3 = new ConditionValue() { ValueType = (UAC.Operation.ValueType)Enum.ToObject(typeof(UAC.Operation.ValueType), Convert.ToInt32(dr["type3"])), Value = dr["value3"] };
                        if (dr["type4"] != DBNull.Value)
                            condition.Values4 = new ConditionValue() { ValueType = (UAC.Operation.ValueType)Enum.ToObject(typeof(UAC.Operation.ValueType), Convert.ToInt32(dr["type4"])), Value = dr["value4"] };
                        if (dr["type5"] != DBNull.Value)
                            condition.Values5 = new ConditionValue() { ValueType = (UAC.Operation.ValueType)Enum.ToObject(typeof(UAC.Operation.ValueType), Convert.ToInt32(dr["type5"])), Value = dr["value5"] };
                    }
                    else
                        condition.ConditionList = children;
                    conditions.Add(condition);
                }
            }
            return conditions;
        }
        #endregion

        public static TeamDef CreateTeamDef(int teamdefid, string description, string targetDescription, bool isSystem)
        {
            string token = RandomString.GetRandomString(10);

            bool isExist = DataHelper.HasRow(string.Format("select * from sy_teamdef where teamdefid={0}", teamdefid));
            if (isExist)
                throw new Exception("已经存在TeamDef相同的项");
            string sqlStr = string.Format("insert into sy_teamdef(teamdefid,description,targetdescription,issystem,token) values({0},'{1}','{2}',{3},'{4}')", teamdefid, DataHelper.EncodeS(description), DataHelper.EncodeS(targetDescription), isSystem ? 1 : 0, token);
            DataHelper.ExecuteNonQuery(sqlStr);
            object id = DataHelper.ExecuteScalar(string.Format("select id from sy_teamdef where token='{0}'", token));
            return new TeamDef() { ID = Convert.ToInt32(id), TeamDefID = teamdefid, Description = description, TargetDescription = targetDescription, IsSystem = isSystem ? 1 : 0 };
        }

        public static List<TeamDef> ListTeamDef()
        {
            List<TeamDef> teamDefs = new List<TeamDef>();
            string sql = "select id,teamdefid,description,targetdescription,issystem from sy_teamdef";
            DataTable result = DataHelper.GetDataTableBySql(sql);
            if (result != null)
            {
                foreach (DataRow dr in result.Rows)
                    teamDefs.Add(new TeamDef(dr));
            }
            return teamDefs;
        }

        public static TeamDef GetTeamDef(int teamDefId)
        {
            string sql = string.Format("select id,teamdefid,description,targetdescription,issystem from sy_teamdef where teamdefid={0}", teamDefId);
            DataTable result = DataHelper.GetDataTableBySql(sql);
            if (result != null)
            {
                foreach (DataRow dr in result.Rows)
                    return new TeamDef(dr);
            }
            return null;
        }

        public static TeamRoleDef CreateTeamRoleDef(int teamroledefid, int teamDefId, string name, string description, bool isSystem)
        {
            string token = RandomString.GetRandomString(10);
            bool isExist = DataHelper.HasRow(string.Format("select * from sy_teamroledef where teamroledefid={0}", teamroledefid));
            if (isExist)
                throw new Exception("已经存在TeamRoleDef相同的项");
            string sqlStr = string.Format("insert into sy_teamroledef(name,description,status,issystem,token,teamdefid,teamroledefid) values('{0}','{1}',1,{2},'{3}',{4},{5})", DataHelper.EncodeS(name), DataHelper.EncodeS(description), isSystem ? 1 : 0, token, teamDefId, teamroledefid);
            DataHelper.ExecuteNonQuery(sqlStr);
            object id = DataHelper.ExecuteScalar(string.Format("select id from sy_teamroledef where token='{0}'", token));
            return new TeamRoleDef() { ID = Convert.ToInt32(id), Description = description, IsSystem = isSystem ? 1 : 0, Name = name, Status = 1, TeamDefID = teamDefId, TeamRoleDefID = teamroledefid };
        }

        public static List<TeamRoleDef> ListTeamRoleDef(int teamDefId)
        {
            List<TeamRoleDef> teamRoleDefs = new List<TeamRoleDef>();
            string sql = "select id,name,description,status,issystem,token,teamdefid,teamroledefid from sy_teamroledef where teamdefid={0}";
            DataTable result = DataHelper.GetDataTableBySql(string.Format(sql, teamDefId));
            if (result != null)
            {
                foreach (DataRow dr in result.Rows)
                    teamRoleDefs.Add(new TeamRoleDef(dr));
            }
            return teamRoleDefs;
        }

        public static Team CreateTeam(int teamDefId, string targetId, string targetType, string targetInfo, string name, string description)
        {
            string token = RandomString.GetRandomString(10);
            string sqlStr = string.Format("insert into sy_team(name,description,status,token,teamdefid,targetid,targettype,targetinfo) values('{0}','{1}',1,'{2}',{3},'{4}','{5}','{6}')", DataHelper.EncodeS(name), DataHelper.EncodeS(description), token, teamDefId, DataHelper.EncodeS(targetId), DataHelper.EncodeS(targetType), DataHelper.EncodeS(targetInfo));
            DataHelper.ExecuteNonQuery(sqlStr);
            object teamId = DataHelper.ExecuteScalar(string.Format("select id from sy_team where token='{0}'", token));
            return new Team() { ID = Convert.ToInt32(teamId), TeamDefID = teamDefId, Name = name, Description = description, TargetID = targetId, TargetType = targetType, TargetInfo = targetInfo };
        }

        public static int GetTeamID(int teamDefId, string targetId)
        {
            string sqlStr = string.Format("select id from sy_team where teamdefid={0} and targetid='{1}'", teamDefId, DataHelper.EncodeS(targetId));
            object teamId = DataHelper.ExecuteScalar(sqlStr);
            return Convert.ToInt32(teamId);
        }

        public static void AssignTeamMember(int teamId, int teamRoleDefId, List<string> arridPeople, bool replace)
        {
            if (replace)
            {
                string sqlDel = string.Format("delete from sy_teammember where teamid={0} and teamroledefid={1}", teamId, teamRoleDefId);
                DataHelper.ExecuteNonQuery(sqlDel);
            }
            string sqlStrFormat = "insert into sy_teammember(teamid,teamroledefid,peopleid) values({0},{1},'{2}')";
            if (arridPeople == null)
                return;
            foreach (string people in arridPeople)
            {
                DataHelper.ExecuteNonQuery(string.Format(sqlStrFormat, teamId, teamRoleDefId, DataHelper.EncodeS(people)));
            }
        }

        public static void RemoveTeamMember(int teamId, int teamRoleDefId, string peopleId)
        {
            string sqlDel = string.Format("delete from sy_teammember where teamid={0} and teamroledefid={1} and peopleid='{2}'", teamId, teamRoleDefId, DataHelper.EncodeS(peopleId));
            DataHelper.ExecuteNonQuery(sqlDel);
        }

        public static List<TeamMember> ListTeamMembers(int teamId, List<int> arridTeamRoleDef)
        {
            List<TeamMember> members = null;
            string sqlStr = null;
            if (arridTeamRoleDef != null && arridTeamRoleDef.Count > 0)
                sqlStr = string.Format("select * from sy_teammember where teamid={0} and {1}", teamId, DataHelper.In("teamroledefid", arridTeamRoleDef, false));
            else
                sqlStr = string.Format("select * from sy_teammember where teamid={0}", teamId);
            DataTable result = DataHelper.GetDataTableBySql(sqlStr);
            if (result != null)
            {
                members = new List<TeamMember>();
                foreach (DataRow dr in result.Rows)
                {
                    members.Add(new TeamMember(dr));
                }
            }
            return members;
        }

        public static List<string> GetTeamMemberArray(int teamId, string teamRoleDefId)
        {
            List<string> members = null;
            string sqlStr = string.Format("select * from sy_teammember where teamid={0} and teamroledefid={1}", teamId, teamRoleDefId);
            DataTable result = DataHelper.GetDataTableBySql(sqlStr);
            if (result != null)
            {
                members = new List<string>();
                foreach (DataRow dr in result.Rows)
                {
                    members.Add(dr["peopleid"].ToString());
                }
            }
            return members;
        }

        public static bool HasExistTeamMember(int teamDefId, int teamRoleDefId, string idPeople)
        {
            string sqlStr = string.Format("select * from sy_teamdef s inner join sy_team t on s.teamdefid=t.teamdefid inner join sy_teammember r on t.id=r.teamid where s.teamdefid={0} and r.teamroledefid={1} and r.peopleid='{2}'", teamDefId, teamRoleDefId, idPeople);
            return DataHelper.HasRow(sqlStr);
        }
    }
}
